﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public enum Side
{
    Left,
    On,
    Right,
}

[Serializable]
public class Line
{
    public Vector3 mPoint1;
    public Vector3 mPoint2;

    public int mLeftTriangle = -1;
    public int mRightTriangle = -1;

    public Line(Vector3 tPoint1, Vector3 tPoint2)
    {
        mPoint1 = tPoint1;
        mPoint2 = tPoint2;
    }

    /// <summary>
    /// 线段是否相交
    /// </summary>
    /// <param name="p1">线段P1P2的P1点</param>
    /// <param name="p2">线段P1P2的P2点</param>
    /// <param name="q1">线段Q1Q2的Q1点</param>
    /// <param name="q2">线段Q1Q2的Q2点</param>
    /// <returns></returns>
    public static bool IsIntersect(Line line1, Line line2)
    {
        Vector3 p1 = line1.mPoint1;
        Vector3 p2 = line1.mPoint2;
        Vector3 q1 = line2.mPoint1;
        Vector3 q2 = line2.mPoint2;


        //排斥试验，判断p1p2在q1q2为对角线的矩形区之外
        if (Mathf.Max(p1.x, p2.x) < Mathf.Min(q1.x, q2.x))
        {//P1P2中最大的x比Q1Q2中的最小x还要小，说明P1P2在Q1Q2的最左点的左侧，不可能相交。
            return false;
        }
        if (Mathf.Min(p1.x, p2.x) > Mathf.Max(q1.x, q2.x))
        {//P1P2中最小的x比Q1Q2中的最大x还要大，说明P1P2在Q1Q2的最右点的右侧，不可能相交。
            return false;
        }
        if (Mathf.Max(p1.z, p2.z) < Mathf.Min(q1.z, q2.z))
        {//P1P2中最大的z比Q1Q2中的最小z还要小，说明P1P2在Q1Q2的最低点的下方，不可能相交。
            return false;
        }
        if (Mathf.Min(p1.z, p2.z) > Mathf.Max(q1.z, q2.z))
        {//P1P2中最小的z比Q1Q2中的最大z还要大，说明P1P2在Q1Q2的最高点的上方，不可能相交。
            return false;
        }

        //跨立试验
        float crossP1P2Q1 = Vector3.Cross(p2 - p1, q1 - p1).y;
        float crossP1Q2P2 = Vector3.Cross(q2 - p1, p2 - p1).y;
        float crossQ1Q2P1 = Vector3.Cross(q2 - q1, p1 - q1).y;
        float crossQ1P2Q2 = Vector3.Cross(p2 - q1, q2 - q1).y;

        bool isIntersect = (crossP1P2Q1 * crossP1Q2P2 >= 0) && (crossQ1Q2P1 * crossQ1P2Q2 >= 0);
        //bool isIntersect = (crossP1P2Q1 * crossP1Q2P2 > 0) && (crossQ1Q2P1 * crossQ1P2Q2 > 0);
        return isIntersect;
    }

    public static bool CheckIntersection(Line line0, Line line1, ref Vector3 ins)
    {
        if (!IsIntersect(line0, line1))
        {
            return false;
        }

        /*
         * L1，L2都存在斜率的情况：
         * 直线方程L1: ( y - y1 ) / ( y2 - y1 ) = ( x - x1 ) / ( x2 - x1 ) 
         * => y = [ ( y2 - y1 ) / ( x2 - x1 ) ]( x - x1 ) + y1
         * 令 a = ( y2 - y1 ) / ( x2 - x1 )
         * 有 y = a * x - a * x1 + y1   .........1
         * 直线方程L2: ( y - y3 ) / ( y4 - y3 ) = ( x - x3 ) / ( x4 - x3 )
         * 令 b = ( y4 - y3 ) / ( x4 - x3 )
         * 有 y = b * x - b * x3 + y3 ..........2
         * 
         * 如果 a = b，则两直线平等，否则， 联解方程 1,2，得:
         * x = ( a * x1 - b * x3 - y1 + y3 ) / ( a - b )
         * y = a * x - a * x1 + y1
         * 
         * L1存在斜率, L2平行Y轴的情况：
         * x = x3
         * y = a * x3 - a * x1 + y1
         * 
         * L1 平行Y轴，L2存在斜率的情况：
         * x = x1
         * y = b * x - b * x3 + y3
         * 
         * L1与L2都平行Y轴的情况：
         * 如果 x1 = x3，那么L1与L2重合，否则平等
         * 
        */

        float x1 = line0.mPoint1.x;
        float x2 = line0.mPoint2.x;
        float x3 = line1.mPoint1.x;
        float x4 = line1.mPoint2.x;

        float y1 = line0.mPoint1.z;
        float y2 = line0.mPoint2.z;
        float y3 = line1.mPoint1.z;
        float y4 = line1.mPoint2.z;

        float k0 = 0, k1 = 0;
        int state = 0;
        if (x1 != x2)
        {
            k0 = (y2 - y1) / (x2 - x1);
            state += 1;
        }
        if (x3 != x4)
        {
            k1 = (y4 - y3) / (x4 - x3);
            state += 2;
        }
        switch (state)
        {
            //L1存在斜率, L2平行Y轴
            case 1:
                ins.x = x3;
                ins.y = 0;
                ins.z = (x3 - x1) * k0 + y1;
                break;
            //L1 平行Y轴，L2存在斜率
            case 2:
                ins.x = x1;
                ins.y = 0;
                ins.z = (x1 - x3) * k1 + y3;
                break;
            case 3:
                float x = (k0 * x1 - k1 * x3 - y1 + y3) / (k0 - k1);
                float y = k0 * x - k0 * x1 + y1;
                ins.x = x;
                ins.y = 0;
                ins.z = y;
                break;
        }
        return true;
    }

    public bool ContainPoint(Vector3 vec)
    {
        if(mPoint1 == vec || mPoint2 == vec)
        {
            return true;
        }
        return false;
    }
}
